<!doctype html>
<html lang="zh-Hans">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name="hugo-theme" content="Axiom 0.7.1">



  <link rel="icon" type="image/png" sizes="32x32" href="/blog/">
  <link rel="icon" type="image/x-icon" href="/blog/">
  <link rel="apple-touch-icon" href="/blog/">
  <link rel="canonical" href="https://Mia-zhao.gitee.io/blog/%E8%99%9A%E6%8B%9F-dom-%E5%92%8C-dom-diff/">
<link rel="preload" as="style" href="/blog/bundle.css?v=1603792187" media="all">
<link rel="stylesheet" href="/blog/bundle.css?v=1603792187" media="all">
<style>.cdata pre{color:#edf2f7;background-color:#2d3748}.cdata :not(pre)>code{color:#805ad5;background-color:#f7fafc}.chroma .err{color:#fed7d7;background-color:#9b2c2c}.chroma .hl{background-color:#4a5568}.chroma .ln{color:#a0aec0}.chroma .k,.chroma .kc,.chroma .kd,.chroma .kn,.chroma .kp,.chroma .kr{color:#63b3ed}.chroma .kt{color:#b794f4}.chroma .na{color:#f6e05e}.chroma .nb{color:#f6ad55}.chroma .nc{color:#fc8181}.chroma .no{color:#68d391}.chroma .nd{color:#fc8181}.chroma .ne{color:#fc8181}.chroma .nf{color:#f6ad55}.chroma .nt{color:#fc8181}.chroma .l{color:#b794f4}.chroma .dl,.chroma .ld,.chroma .s,.chroma .s2,.chroma .sa,.chroma .sb,.chroma .sc,.chroma .sd{color:#68d391}.chroma .se{color:#a0aec0}.chroma .s1,.chroma .sh,.chroma .si,.chroma .sr,.chroma .ss,.chroma .sx{color:#68d391}.chroma .il,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .mo{color:#b794f4}.chroma .o,.chroma .ow{color:#90cdf4}.chroma .p{color:#cbd5e0}.chroma .c,.chroma .c1,.chroma .ch,.chroma .cm,.chroma .cp,.chroma .cpf,.chroma .cs{color:#a0aec0}.chroma .ge{font-style:italic}.chroma .gs{font-weight:700}</style>



<title>虚拟 DOM 和 DOM Diff : Mia&#39;s Blog Posts</title>

<meta property="og:title" content="虚拟 DOM 和 DOM Diff">
<meta property="og:site_name" content="Mia&#39;s Blog Posts">
<meta property="og:url" content="https://Mia-zhao.gitee.io/blog/%E8%99%9A%E6%8B%9F-dom-%E5%92%8C-dom-diff/">
<link rel="image_src" href="https://Mia-zhao.gitee.io/blog/">
<meta property="og:image" content="https://Mia-zhao.gitee.io/blog/">
<meta property="og:image:width" content="">
<meta property="og:image:height" content="">
<meta property="og:type" content="article">
<meta property="og:locale" content="zh_Hans">
<meta property="og:description" content="在 React 和 Vue 中，对于每一个 DOM 对象，有一个对应的虚拟 DOM (virtual DOM) 对象。React 和 Vue 对虚拟 DOM 对象的呈现语法不同，但代表的内容是一样的。 开发者在 Vue 中使用 x-template，在 React 中使用 jsx，当渲染他们时，每一个虚拟 DOM 更新，React 和 Vue 则对比虚拟DOM以及旧版本虚拟 DOM 然后对改变了的 DOM 对象进行更新 (这个过程就是 DOM diff)。 虚拟 DOM 是什么 以 Vue 为例，Vue 的模板接受代码&amp;lt;h1&amp;gt;{{ blogTitle }}&amp;lt;/h1&amp;gt;表示期望的h1标签内容，Vue 通过 createElement(&#39;h1&#39;, this.blogTitle) 建立 VNode 存储页面需要渲染的节点等信息。Vue 组件建立的整个 VNode 被称为虚拟 DOM。 虚拟 DOM 的优点  快速 虚拟 DOM 通过减少 DOM 操作达到快速渲染。相比较于 DOM 原生操作，虚拟 DOM 可以  将多个操作合并为一个操作 借助 DOM diff 省去多余操作   跨平台">
<meta name="description" content="在 React 和 Vue 中，对于每一个 DOM 对象，有一个对应的虚拟 DOM (virtual DOM) 对象。React 和 Vue 对虚拟 DOM 对象的呈现语法不同，但代表的内容是一样的。 开发者在 Vue 中使用 x-template，在 React 中使用 jsx，当渲染他们时，每一个虚拟 DOM 更新，React 和 Vue 则对比虚拟DOM以及旧版本虚拟 DOM 然后对改变了的 DOM 对象进行更新 (这个过程就是 DOM diff)。 虚拟 DOM 是什么 以 Vue 为例，Vue 的模板接受代码&amp;lt;h1&amp;gt;{{ blogTitle }}&amp;lt;/h1&amp;gt;表示期望的h1标签内容，Vue 通过 createElement(&#39;h1&#39;, this.blogTitle) 建立 VNode 存储页面需要渲染的节点等信息。Vue 组件建立的整个 VNode 被称为虚拟 DOM。 虚拟 DOM 的优点  快速 虚拟 DOM 通过减少 DOM 操作达到快速渲染。相比较于 DOM 原生操作，虚拟 DOM 可以  将多个操作合并为一个操作 借助 DOM diff 省去多余操作   跨平台">
<meta property="og:updated_time" content="2020-09-16T09:00:00Z">
<meta property="fb:app_id" content="">
<meta name="author" content="Mia Zhao">
<meta property="article:author" content="https://mia-zhao.gitee.io/">
<meta property="article:published_time" content="2020-09-16T09:00:00Z">
<meta property="article:modified_time" content="2020-09-16T09:00:00Z">
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "虚拟 DOM 和 DOM Diff",
  "alternativeHeadline": "在 React 和 Vue 中，对于每一个 DOM 对象，有一个对应的虚拟 DOM (virtual DOM) 对象。React 和 Vue 对虚拟 DOM 对象的呈现语法不同，但代表的内容是一样的。 开发者在 Vue 中使用 x-template，在 React 中使用 jsx，当渲染他们时，每一个虚拟 DOM 更新，React 和 Vue 则对比虚拟DOM以及旧版本虚拟 DOM 然后对改变了的 DOM 对象进行更新 (这个过程就是 DOM diff)。 虚拟 DOM 是什么 以 Vue 为例，Vue 的模板接受代码\u0026lt;h1\u0026gt;{{ blogTitle }}\u0026lt;/h1\u0026gt;表示期望的h1标签内容，Vue 通过 createElement('h1', this.blogTitle) 建立 VNode 存储页面需要渲染的节点等信息。Vue 组件建立的整个 VNode 被称为虚拟 DOM。 虚拟 DOM 的优点  快速 虚拟 DOM 通过减少 DOM 操作达到快速渲染。相比较于 DOM 原生操作，虚拟 DOM 可以  将多个操作合并为一个操作 借助 DOM diff 省去多余操作   跨平台",
  "url": "https://Mia-zhao.gitee.io/blog/%E8%99%9A%E6%8B%9F-dom-%E5%92%8C-dom-diff/",
  "image": "https://Mia-zhao.gitee.io/blog/",
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://Mia-zhao.gitee.io/blog/%E8%99%9A%E6%8B%9F-dom-%E5%92%8C-dom-diff/"
  },
  "description": "在 React 和 Vue 中，对于每一个 DOM 对象，有一个对应的虚拟 DOM (virtual DOM) 对象。React 和 Vue 对虚拟 DOM 对象的呈现语法不同，但代表的内容是一样的。 开发者在 Vue 中使用 x-template，在 React 中使用 jsx，当渲染他们时，每一个虚拟 DOM 更新，React 和 Vue 则对比虚拟DOM以及旧版本虚拟 DOM 然后对改变了的 DOM 对象进行更新 (这个过程就是 DOM diff)。 虚拟 DOM 是什么 以 Vue 为例，Vue 的模板接受代码\u0026lt;h1\u0026gt;{{ blogTitle }}\u0026lt;/h1\u0026gt;表示期望的h1标签内容，Vue 通过 createElement('h1', this.blogTitle) 建立 VNode 存储页面需要渲染的节点等信息。Vue 组件建立的整个 VNode 被称为虚拟 DOM。 虚拟 DOM 的优点  快速 虚拟 DOM 通过减少 DOM 操作达到快速渲染。相比较于 DOM 原生操作，虚拟 DOM 可以  将多个操作合并为一个操作 借助 DOM diff 省去多余操作   跨平台",
  "author": {
    "@type": "Person",
    "name": "Mia Zhao"
  },
  "publisher": {
    "@type": "Organization",
    "name": "Mia's Blog Posts",
    "logo": {
      "@type": "ImageObject",
      "url": "https://Mia-zhao.gitee.io/blog/"
    }
  },
  "datePublished": "2020-09-16T09:00:00Z",
  "dateModified": "2020-09-16T09:00:00Z",
  "articleBody": "\u003cp\u003e在 React 和 Vue 中，对于每一个 DOM 对象，有一个对应的虚拟 DOM (virtual DOM) 对象。React 和 Vue 对虚拟 DOM 对象的呈现语法不同，但代表的内容是一样的。\u003cbr\u003e\n\u003cbr\u003e\n开发者在 Vue 中使用 x-template，在 React 中使用 jsx，当渲染他们时，每一个虚拟 DOM 更新，React 和 Vue 则对比虚拟DOM以及旧版本虚拟 DOM 然后对改变了的 DOM 对象进行更新 (这个过程就是 DOM diff)。\u003c/p\u003e\n\u003ch2 id=\"虚拟-dom-是什么\"\u003e虚拟 DOM 是什么\u003c/h2\u003e\n\u003cp\u003e以 Vue 为例，Vue 的模板接受代码\u003ccode\u003e\u0026lt;h1\u0026gt;{{ blogTitle }}\u0026lt;/h1\u0026gt;\u003c/code\u003e表示期望的\u003ccode\u003eh1\u003c/code\u003e标签内容，Vue 通过 \u003ccode\u003ecreateElement('h1', this.blogTitle)\u003c/code\u003e 建立 VNode 存储页面需要渲染的节点等信息。Vue 组件建立的整个 VNode 被称为虚拟 DOM。\u003c/p\u003e\n\u003ch2 id=\"虚拟-dom-的优点\"\u003e虚拟 DOM 的优点\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e快速\u003cbr\u003e\n虚拟 DOM 通过减少 DOM 操作达到快速渲染。相比较于 DOM 原生操作，虚拟 DOM 可以\n\u003cul\u003e\n\u003cli\u003e将多个操作合并为一个操作\u003c/li\u003e\n\u003cli\u003e借助 DOM diff 省去多余操作\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e跨平台\u003cbr\u003e\n虚拟 DOM 本质是 JavaScript 对象，因此可以转变为 DOM、小程序、iOS 应用、Android 应用\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"虚拟-dom-的缺点\"\u003e虚拟 DOM 的缺点\u003c/h2\u003e\n\u003cp\u003e虚拟 DOM 需要额外的创建函数，例如\u003ccode\u003ecreateElement\u003c/code\u003e；在 Vue 和 React 中可以用 x-template 和 jsx 语法来简化方便开发，这样增加了对 Vue 和 React 编译打包的依赖。\u003c/p\u003e\n\u003ch2 id=\"dom-diff-是什么\"\u003eDOM diff 是什么\u003c/h2\u003e\n\u003cp\u003eDOM diff 是对比发现虚拟 DOM 变化的算法。大致步骤是：\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e对比虚拟 DOM 和旧版本虚拟 DOM 树\r\n  -\u0026gt; 对需要更新的组件或标签节点\r\n    |\r\n    -\u0026gt; 比较类型或标签名，如果相同则只更新属性，否则直接替换，然后递归对比\r\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"dom-diff-的优点\"\u003eDOM diff 的优点\u003c/h2\u003e\n\u003cp\u003eDOM diff 对比出改变的虚拟 DOM 进行渲染，减去不必要渲染，这样加快渲染效率。\u003c/p\u003e\n\u003ch2 id=\"dom-diff-的问题\"\u003eDOM diff 的问题\u003c/h2\u003e\n\u003cp\u003eDOM diff 流程是逐级比较，若新版本虚拟 DOM 删掉其中一个节点，DOM diff 算法会比较新版虚拟 DOM 的下一个节点与原版本中被删掉的节点。因此，若多个重复节点的 List 是动态变化的，DOM diff 可能会造成问题，正如 \u003ca href=\"https://reactjs.org/docs/lists-and-keys.html#keys\"\u003eReact Lists and Keys\u003c/a\u003e 中提到的，需要提供独特的 IDs 给 lists。\u003c/p\u003e"
}
</script>

<link rel="preload" as="script" href="/blog/bundle.js?v=1603792187">


</head>
<body>

  <header id="nav" class="header">
  <div class="ax-l-i max-w-6xl">
    <div class="ax-logo">
      <a class="block" href="/blog/" title="Mia&#39;s Blog Posts"><span class="font-semibold text-raven-900">Mia's Blog Posts</span></a>
    </div>
    <div class="ax-user">
      <a class="p-2 w-8 h-8 block text-raven-500 hover:text-gray-800 focus:text-gray-800 focus:outline-none" target="_blank" rel="noopener nofollow" href="https://www.google.com/search?q=site:https://Mia-zhao.gitee.io/blog/" title="Search">
        <svg class="fill-current" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M2.67 12.804c0-5.6 4.544-10.134 10.133-10.134s10.134 4.544 10.134 10.134-4.544 10.133-10.134 10.133S2.67 18.393 2.67 12.804zm28.943 16.923l-8.868-8.868c4.287-5.3 3.68-13.012-1.378-17.57S8.564-1.066 3.75 3.75s-5.017 12.558-.46 17.618 12.28 5.665 17.57 1.378l8.868 8.868a1.33 1.33 0 0 0 2.231-.597c.123-.46-.008-.952-.345-1.29h0z"/></svg>

      </a>
      <a class="p-2 block text-base leading-none text-raven-500 hover:text-gray-800 focus:text-gray-800 focus:outline-none" href="/blog/posts/">
        Posts
      </a>
    </div>
  </div>

  
</header>

  <main>
<div class="default-single">
  <div class="ax-title ax-l-o">
    <div class="ax-l-i max-w-680">
      <h1 class="post-title font-content-title font-normal leading-tight tracking-default text-40">虚拟 DOM 和 DOM Diff</h1>

      <div class="ax-meta flex items-center mt-5">
        <div class="flex-grow min-w-0">
          <div class="flex items-center">
  <div class="flex-shrink-0">
    <img
    class="w-12 h-12 sm:w-14 sm:h-14 object-cover p-3px rounded-full border border-blue-300"
    src="/blog/images/author/default.webp"
    alt="Mia Zhao">
  </div>
  <div class="flex-shrink-0 ml-2 leading-tight font-content-sans">
    <a class="block text-sm text-raven-800 hover:text-raven-900 hover:underline focus:underline" target="_blank" rel="noopener nofollow" title="Mia Zhao" href="https://mia-zhao.gitee.io/">Mia Zhao</a>
    <time class="text-sm text-raven-500" datetime="2020-09-16T09:00:00Z">Sep 16, 2020 5:00PM</time>
  </div>
</div>

        </div>
        <div>
          <div class="flex items-center">
  <a class="flex-shrink-0 block text-raven-800 hover:text-raven-900" target="_blank" rel="noopener nofollow" title="Share on Twitter" href="https://twitter.com/intent/tweet?text=%e8%99%9a%e6%8b%9f%20DOM%20%e5%92%8c%20DOM%20Diff%20by%20%40%25%21s%28%3cnil%3e%29%20https%3a%2f%2fMia-zhao.gitee.io%2fblog%2f%25E8%2599%259A%25E6%258B%259F-dom-%25E5%2592%258C-dom-diff%2f"><svg class="w-6 h-6 fill-current" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M32 6.078c-1.2.522-2.458.868-3.78 1.036 1.36-.812 2.398-2.088 2.886-3.626a13.11 13.11 0 0 1-4.16 1.588C25.742 3.794 24.026 3 22.154 3a6.56 6.56 0 0 0-6.556 6.562c0 .52.044 1.02.152 1.496-5.454-.266-10.28-2.88-13.522-6.862-.566.982-.898 2.106-.898 3.316a6.57 6.57 0 0 0 2.914 5.452 6.48 6.48 0 0 1-2.964-.808v.072c0 3.188 2.274 5.836 5.256 6.446-.534.146-1.116.216-1.72.216-.42 0-.844-.024-1.242-.112.85 2.598 3.262 4.508 6.13 4.57a13.18 13.18 0 0 1-8.134 2.798c-.538 0-1.054-.024-1.57-.1C2.906 27.93 6.35 29 10.064 29c12.072 0 18.672-10 18.672-18.668 0-.3-.01-.57-.024-.848C30.014 8.56 31.108 7.406 32 6.078z"/></svg>
</a>
  <a class="ml-3 flex-shrink-0 block text-raven-800 hover:text-raven-900" target="_blank" rel="noopener nofollow" title="Share on Facebook" href="https://www.facebook.com/dialog/share?app_id=&display=page&href=https%3a%2f%2fMia-zhao.gitee.io%2fblog%2f%25E8%2599%259A%25E6%258B%259F-dom-%25E5%2592%258C-dom-diff%2f"><svg class="w-6 h-6 fill-current" viewBox="-7 -3.5 39 39" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M30.234 0H1.765C.8.001 0 .79 0 1.766v28.47C.001 31.2.79 32 1.766 32h15.328V19.625h-4.156V14.78h4.156v-3.564c0-4.134 2.523-6.384 6.21-6.384 1.766 0 3.284.13 3.726.2v4.32h-2.543c-2.006 0-2.394.953-2.394 2.352v3.085h4.797l-.625 4.844h-4.172V32h8.14C31.21 32 32 31.2 32 30.234V1.765C32 .8 31.21 0 30.234 0z"/></svg>
</a>
</div>

        </div>
      </div>
    </div>
  </div><div class="ax-content ax-l-o">
    <div class="ax-l-i max-w-680">
      <article class="cdata">
<p>在 React 和 Vue 中，对于每一个 DOM 对象，有一个对应的虚拟 DOM (virtual DOM) 对象。React 和 Vue 对虚拟 DOM 对象的呈现语法不同，但代表的内容是一样的。<br>
<br>
开发者在 Vue 中使用 x-template，在 React 中使用 jsx，当渲染他们时，每一个虚拟 DOM 更新，React 和 Vue 则对比虚拟DOM以及旧版本虚拟 DOM 然后对改变了的 DOM 对象进行更新 (这个过程就是 DOM diff)。</p>
<h2 id="虚拟-dom-是什么">虚拟 DOM 是什么</h2>
<p>以 Vue 为例，Vue 的模板接受代码<code>&lt;h1&gt;{{ blogTitle }}&lt;/h1&gt;</code>表示期望的<code>h1</code>标签内容，Vue 通过 <code>createElement('h1', this.blogTitle)</code> 建立 VNode 存储页面需要渲染的节点等信息。Vue 组件建立的整个 VNode 被称为虚拟 DOM。</p>
<h2 id="虚拟-dom-的优点">虚拟 DOM 的优点</h2>
<ol>
<li>快速<br>
虚拟 DOM 通过减少 DOM 操作达到快速渲染。相比较于 DOM 原生操作，虚拟 DOM 可以
<ul>
<li>将多个操作合并为一个操作</li>
<li>借助 DOM diff 省去多余操作</li>
</ul>
</li>
<li>跨平台<br>
虚拟 DOM 本质是 JavaScript 对象，因此可以转变为 DOM、小程序、iOS 应用、Android 应用</li>
</ol>
<h2 id="虚拟-dom-的缺点">虚拟 DOM 的缺点</h2>
<p>虚拟 DOM 需要额外的创建函数，例如<code>createElement</code>；在 Vue 和 React 中可以用 x-template 和 jsx 语法来简化方便开发，这样增加了对 Vue 和 React 编译打包的依赖。</p>
<h2 id="dom-diff-是什么">DOM diff 是什么</h2>
<p>DOM diff 是对比发现虚拟 DOM 变化的算法。大致步骤是：</p>
<pre><code>对比虚拟 DOM 和旧版本虚拟 DOM 树
  -&gt; 对需要更新的组件或标签节点
    |
    -&gt; 比较类型或标签名，如果相同则只更新属性，否则直接替换，然后递归对比
</code></pre><h2 id="dom-diff-的优点">DOM diff 的优点</h2>
<p>DOM diff 对比出改变的虚拟 DOM 进行渲染，减去不必要渲染，这样加快渲染效率。</p>
<h2 id="dom-diff-的问题">DOM diff 的问题</h2>
<p>DOM diff 流程是逐级比较，若新版本虚拟 DOM 删掉其中一个节点，DOM diff 算法会比较新版虚拟 DOM 的下一个节点与原版本中被删掉的节点。因此，若多个重复节点的 List 是动态变化的，DOM diff 可能会造成问题，正如 <a href="https://reactjs.org/docs/lists-and-keys.html#keys">React Lists and Keys</a> 中提到的，需要提供独特的 IDs 给 lists。</p>

      </article>
      

      

    </div>
  </div>
</div>

  </main>
  <footer class="footer">
  <div class="ax-l-i max-w-6xl">
    <nav class="flex items-center justify-center">
      <a class="ml-3 first:ml-0 text-sm text-gray-600 hover:text-gray-800" href="/blog/posts/">Posts</a>
      <a class="ml-3 first:ml-0 text-sm text-gray-600 hover:text-gray-800" href="/blog/contact/">Contact</a>
    </nav>

    <div class="footer-copyright text-sm text-center text-gray-500 mt-4">
      &#169; -2020 Mia&#39;s Blog Posts
    </div>
    <div class="text-sm sm:text-xs text-center text-gray-500 mt-2">
      Powered by <a href="https://www.axiomtheme.com/?utm_source=theme-footer&utm_medium=website&utm_campaign=referral">Axiom</a>
    </div>
  </div>
</footer>

<script src="/blog/bundle.js?v=1603792187"></script>


</body>
</html>
